package org.budo.weixin.work.api.entity;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

import org.budo.support.lang.util.MapUtil;
import org.budo.support.lang.util.NumberUtil;
import org.budo.support.lang.util.StringUtil;
import org.budo.time.Time;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;

import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;
import lombok.extern.slf4j.Slf4j;

/**
 * @author lmw
 */
@Getter
@Setter
@NoArgsConstructor
@ToString
@Slf4j
public class ApprovalDetailImpl implements ApprovalDetail, Serializable {
    private static final long serialVersionUID = 639742016641769044L;

    private String json;

    public ApprovalDetailImpl(String json) {
        this.json = json;
    }

    public String getTemplateId() {
        JSONObject info = this._info();
        return info.getString("template_id");
    }

    public String getSpName() {
        JSONObject info = this._info();
        return info.getString("sp_name");
    }

    public String getSpStatus() {
        JSONObject info = this._info();
        return info.getString("sp_status");
    }

    public String getApplyerUserId() {
        JSONObject info = this._info();
        JSONObject applyer = info.getJSONObject("applyer");
        return applyer.getString("userid");
    }

    public Long getApplyTime() {
        JSONObject info = this._info();
        return info.getLong("apply_time");
    }

    public List<Map<String, Object>> getApplyDataMapList() {
        List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();

        if (StringUtil.isNullOrEmpty(this.getJson())) {
            return list;
        }

        JSONObject jsonObject = JSON.parseObject(this.getJson());
        JSONObject info = jsonObject.getJSONObject("info");
        if (null == info) {
            log.warn("#54 getApplyDataMapList, info=" + info + ", json=" + this.getJson());
            return list;
        }

        JSONObject apply_data = info.getJSONObject("apply_data");
        if (null == apply_data) {
            log.error("#60 getApplyDataMapList, apply_data=" + apply_data + ", json=" + this.getJson());
            return list;
        }

        JSONArray contents = apply_data.getJSONArray("contents");
        if (null == contents) {
            log.error("#66 getApplyDataMapList, contents=" + contents + ", json=" + this.getJson());
            return list;
        }

        for (Object each : contents) {
            JSONObject content = (JSONObject) each;

            String control = content.getString("control");
            String id = content.getString("id");

            String titleText = this._titleText(content);

            JSONObject value = content.getJSONObject("value");

            //
            String text = value.getString("text");
            if (StringUtil.isNotNullOrEmpty(text)) {
                list.add(MapUtil.stringObjectMap("name", titleText, //
                        "id", id, //
                        "control", control, //
                        "_value", text));
                continue;
            }

            //
            JSONObject selector = value.getJSONObject("selector");
            if (null != selector && !selector.isEmpty()) {
                JSONArray options = selector.getJSONArray("options");
                JSONObject option = options.getJSONObject(0); // 如果是多选，没有处理
                String key = option.getString("key");

                list.add(MapUtil.stringObjectMap("name", titleText, //
                        "id", id, //
                        "control", control, //
                        "_value", key));
                continue;
            }

            //
            if ("Money".equals(control)) {
                String new_money = value.getString("new_money");
                list.add(MapUtil.stringObjectMap("name", titleText, //
                        "id", id, //
                        "control", control, //
                        "_value", new_money));
                continue;
            }

            //
            if ("File".equals(control)) {
                JSONArray files = value.getJSONArray("files");

                List<String> fileIds = new ArrayList<String>();

                for (Object _file : files) {
                    JSONObject file = (JSONObject) _file;
                    String file_id = file.getString("file_id");
                    fileIds.add(file_id);
                }

                list.add(MapUtil.stringObjectMap("name", titleText, //
                        "id", id, //
                        "control", control, //
                        "_value", StringUtil.join(fileIds)));
                continue;
            }

            if ("Date".equals(control)) {
                JSONObject date = value.getJSONObject("date");
                String s_timestamp = date.getString("s_timestamp");
                Date dateValue = Time.when(NumberUtil.toLong(s_timestamp) * 1000).toDate();

                list.add(MapUtil.stringObjectMap("name", titleText, //
                        "id", id, //
                        "control", control, //
                        "_value", dateValue));
                continue;
            }

            log.error("#103 content=" + content);
        }

        return list;
    }

    private JSONObject _info() {
        JSONObject jsonObject = JSON.parseObject(this.getJson());
        JSONObject info = jsonObject.getJSONObject("info");
        return info;
    }

    private String _titleText(JSONObject content) {
        JSONArray titles = content.getJSONArray("title");
        for (Object e : titles) {
            JSONObject title = (JSONObject) e;
            return title.getString("text");
        }

        log.error("#113 titleText null, content=" + content);
        return null;
    }

    @Override
    public String getStatuChangeEvent() {
        return STATU_999;
    }

    @Override
    public String getSpNo() {
        JSONObject info = this._info();
        return info.getString("sp_no");
    }

    @Override
    public String getRequestBody() {
        return this.json;
    }

    @Override
    public List<SpRecord> getSpRecords() {
        JSONObject jsonObject = JSON.parseObject(this.getJson());
        JSONObject info = jsonObject.getJSONObject("info");
        JSONArray spRecordArray = info.getJSONArray("sp_record");

        List<SpRecord> spRecordList = new ArrayList<SpRecord>();

        Integer index = 0;
        for (Object spRecordEach : spRecordArray) {
            ApprovalDetailSpRecord spRecord = new ApprovalDetailSpRecord((JSONObject) spRecordEach);
            spRecord.setIndex(index);
            spRecordList.add(spRecord);

            index++;
        }

        return spRecordList;
    }

    @Override
    public List<String> getSpRecordApproverUserIdList() {
        List<String> users = new ArrayList<String>();

        JSONObject info = this._info();
        JSONArray spRecordArray = info.getJSONArray("sp_record");
        for (Object _record : spRecordArray) {
            JSONObject spRecord = (JSONObject) _record;
            JSONArray details = spRecord.getJSONArray("details");
            for (Object _detail : details) {
                JSONObject detail = (JSONObject) _detail;

                JSONObject approver = detail.getJSONObject("approver");
                String userId = approver.getString("userid");

                users.add(userId);
            }
        }

        return users;
    }

    @Override
    public Boolean allAgreed() {
        JSONObject info = this._info();
        JSONArray spRecordArray = info.getJSONArray("sp_record");

        for (Object record : spRecordArray) {
            JSONObject spRecord = (JSONObject) record;
            JSONArray details = spRecord.getJSONArray("details");

            for (Object _detail : details) {
                JSONObject detail = (JSONObject) _detail;
                String sp_status = detail.getString("sp_status");

                if (!StringUtil.equals("2", sp_status) //
                        && !StringUtil.equals("4", sp_status)) { // 1-审批中；2-已同意；3-已驳回；4-已转审
                    log.info("#234 not allAgreed, spRecord=" + spRecord + ", this=" + this);
                    return false;
                }
            }
        }

        return true;
    }

    @Override
    public Boolean anyReject() {
        JSONObject info = this._info();
        JSONArray spRecordArray = info.getJSONArray("sp_record");

        for (Object record : spRecordArray) {
            JSONObject spRecord = (JSONObject) record;
            JSONArray details = spRecord.getJSONArray("details");

            for (Object detail : details) {
                JSONObject de = (JSONObject) detail;
                String sp_status = de.getString("sp_status");

                if (StringUtil.equals("3", sp_status)) { // 1-审批中；2-已同意；3-已驳回；4-已转审
                    log.info("#263 find one reject, spRecord=" + spRecord + ", this=" + this);
                    return true;
                }
            }
        }

        return false;
    }

    @Override
    public SpRecordDetail getLastSpRecordDetailProcessed() {
        log.debug("#237 getLastSpRecordDetailProcessed return null, this={}", this);
        return null;
    }

    @Override
    public Integer getSpRecordSize() {
        log.debug("#243 getSpRecordSize return -1, this={}", this);
        return -1;
    }
}